#pragma once

#include "fixed_point_helper.h"

namespace krryn{
namespace system_imp{
	template<typename _Description, typename _Type = float>
	class scan_convert{
	public:
		typedef typename _Description::vertex_type vertex_type;

		static const size_t m_Count = _Description::m_Size ;

		bool m_IsLeftSide;

		_Type m_Deltas[m_Count];
		_Type m_Values[m_Count];

		forceinline void recalculate_slopes(const scan_convert &a_Scan, _Type a_DeltaInv){
			for(size_t i = 0; i < m_Count; i++){
				m_Deltas[i] = mul<_Type>(a_Scan.m_Values[i] - m_Values[i], a_DeltaInv);
			}
		}

		forceinline void init_edge(const _Type *a_Top, const _Type *a_Bottom, _Type a_DeltaInv){
			for(size_t i = 0; i < m_Count; i++){
				m_Values[i] = a_Bottom[i];
			}

			for(size_t i = 0; i < m_Count; i++){
				m_Deltas[i] = mul<_Type>(a_Top[i] - a_Bottom[i], a_DeltaInv);
			}
		}

		/// correct for sub-pixel and sub-texel accuracy
		forceinline void sub_pixel(_Type a_Subpixel){
			for(size_t i = 0; i < m_Count; i++){
				m_Values[i] += mul<_Type>(m_Deltas[i], a_Subpixel);
			}
		}

		/// interpolate the values using the deltas calculated previously
		forceinline void interpolate(){
			for(size_t i = 0; i < m_Count; i++){
				m_Values[i] += m_Deltas[i];
			}
		}

		/// skip ahead till we're at a correct offset again
		/// (needed due to rounding errors after drawing the first sub-triangle)
		forceinline void skip(const _Type * a_Vertex, _Type a_Delta){
			for(size_t i = 0; i < m_Count; i++){
				m_Values[i] = a_Vertex[i] + mul<_Type>(m_Deltas[i], a_Delta);
			}
		}
	};
}
}